<template>
  <div class="content">
    <el-upload
      ref="fileUpload"
      :http-request="manualUpload"
      :before-upload="beforeUpload"
      :before-remove="beforeRemove"
      :on-success="handleSuccess"
      :on-remove="handleRemove"
      :on-exceed="handleExceed"
      :drag="listType!=='picture-card'"
      :accept="accept"
      :multiple="limit > 1"
      :limit="limit===1?2:limit"
      :file-list="fileList"
      :list-type="listType"
      action=""
    >

      <i v-if="listType==='picture-card'" class="el-icon-plus"/>

      <i v-if="listType!=='picture-card'" class="el-icon-upload" />
      <div v-if="listType!=='picture-card'" class="el-upload__text">
        将文件拖到此处，或
        <em>点击上传</em>
      </div>
      <div v-if="tips" slot="tip" class="el-upload__tip">{{ tips }}</div>
    </el-upload>
  </div>
</template>

<script>
import { buildDir } from '@/utils/file-utils'
import { fetchSts } from '@/api/sys/config/oss'
import { compressImage } from '@/utils/upload'
const OSS = require('ali-oss')

export default {
  name: 'FileUploadOss',
  props: {
    value: {
      type: Array,
      default() {
        return []
      }
    },
    accept: String,
    tips: String,
    listType: String,
    limit: {
      type: Number,
      default: 1
    },
    compress: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      fileList: [],
      fileNames: {},
      // 文件及授权信息
      dataObj: {},
      conf: {
        host: ''
      },
      client: null
    }
  },
  watch: {
    // 检测查询变化
    value: {
      handler(val) {
        this.fileList = val
      }
    }
  },

  mounted() {
    this.fetchConfig()
  },

  created() {
    this.fillValue()
  },
  methods: {

    // 填充数据
    fillValue() {
      this.fileList = this.value
    },

    // 获取基础配置
    fetchConfig() {
      // 获得上传令牌
      fetchSts().then(res => {
        const data = res.data

        this.client = new OSS({
          // yourRegion填写Bucket所在地域。以华东1（杭州）为例，Region填写为oss-cn-hangzhou。
          region: data.region,
          // 从STS服务获取的临时访问密钥（AccessKey ID和AccessKey Secret）。
          accessKeyId: data.accessKeyId,
          accessKeySecret: data.accessKeySecret,
          // 从STS服务获取的安全令牌（SecurityToken）。
          stsToken: data.securityToken,
          // 刷新临时访问凭证的时间间隔，单位为毫秒。
          refreshSTSTokenInterval: 300000,
          // 填写Bucket名称。
          bucket: data.bucket
        })
        // 配置信息
        this.conf = data
      }).catch(err => {
        this.$message.error(`获取上传令牌失败： ${err} `)
      })
    },

    // 文件超出个数限制时的钩子
    handleExceed() {
      this.$message.warning(`每次只能上传 ${this.limit} 个文件`)
    },

    // 删除文件之前的钩子
    beforeRemove() {
      return this.$confirm(`确定移除文件吗？`)
    },

    // 移除文件
    handleRemove(file) {
      // 移除文件
      for (let i = 0; i<this.fileList.length; i++) {
        if (file.uid === this.fileList[i].uid) {
          this.fileList.splice(i, 1)
        }
      }
    },

    // 文件上传成功时的钩子
    handleSuccess(response, file, fileList) {
      // 只能传一个的进行替换
      if (this.limit === 1 && fileList.length>1) {
        const url = this.conf.url + this.fileNames[file.uid]
        // 反转并保留一个
        fileList = [{ url: url, name: url }]
      } else {
        // 上传成功替换服务端URL
        for (let i = 0; i< fileList.length; i++) {
          if (file.uid === fileList[i].uid) {
            fileList[i].url = this.conf.url + this.fileNames[file.uid]
          }
        }
      }

      this.$emit('input', fileList)
    },
    // 文件上传前的校验
    beforeUpload(file) {
      this.$emit('select', file.name)
      return compressImage(file, this.compress)
    },

    // 手动上传文件
    async manualUpload(param) {
      const file = param.file
      const key = this.buildName(file)
      this.fileNames[file.uid] = key

      // 分片上传。
      await this.client.multipartUpload(key, file, {
        progress: (p) => {
          const percent = Math.round(p * 100)
          param.onProgress({ percent: percent })
        }
      })
    },

    // 重命名文件
    buildName(file) {
      const temporary = file.name.lastIndexOf('.')
      const fileNameLength = file.name.length
      const fileFormat = file.name.substring(
        temporary + 1,
        fileNameLength
      )
      return buildDir() + '.' + fileFormat
    }
  }
}
</script>
